﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AMail.Modules.Folders.Interfaces;
using AMail.Common.Interfaces.Data;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;

namespace AMail.Modules.Folders.ViewModels
{
  public class FolderViewModel : IFolderViewModel
  {
    private bool isExpanded;
    private bool isSelected;

    public FolderViewModel(IMailFolder folder, IFolderViewModel parent)
    {
      this.Folder = folder;
      this.Parent = parent;
      this.Children = new ObservableCollection<IFolderViewModel>();
      foreach (IMailFolder subfolder in folder.Subfolders)
        this.Children.Add(new FolderViewModel(subfolder, this));

      this.Folder.Messages.CollectionChanged += new NotifyCollectionChangedEventHandler(Messages_CollectionChanged);
      this.Folder.Subfolders.CollectionChanged += new NotifyCollectionChangedEventHandler(Subfolders_CollectionChanged);
    }

    void Messages_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
      // the count of messages has changed, so the header changes too
      OnPropertyChanged("Header");
    }

    public IFolderViewModel FindViewModelByFolder(IMailFolder subfolder)
    {
      foreach (FolderViewModel viewModel in this.Children)
      {
        if (viewModel.Folder == subfolder)
          return viewModel;
      }

      return null;
    }

    void Subfolders_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
      if (e.OldItems != null)
      {
        foreach (IMailFolder subfolder in e.OldItems)
        {
          var viewModel = FindViewModelByFolder(subfolder);
          if (viewModel != null)
            this.Children.Remove(viewModel);
        }
      }

      if (e.NewItems != null)
      {
        int index = e.NewStartingIndex;
        foreach (IMailFolder subfolder in e.NewItems)
        {
          var viewModel = new FolderViewModel(subfolder, this);
          this.Children.Insert(index++, viewModel);
        }
      }

      if (e.Action == NotifyCollectionChangedAction.Reset)
      {
        this.Children.Clear();
      }
    }

    #region IFolderViewModel Members

    public IMailFolder Folder { get; private set; }

    public string Header
    {
      get
      {
        if (this.Folder.Messages.Count == 0)
          return this.Folder.Name;
        else
          return string.Format("{0} ({1})", this.Folder.Name, this.Folder.Messages.Count);
      }
      set
      {
        if (value == null)
          return;

        string msgCountSuffix = string.Format("({0})", this.Folder.Messages.Count);
        if (value.EndsWith(msgCountSuffix))
        {
          value = value.Replace(msgCountSuffix, string.Empty);
          value = value.Trim();
        }

        if (this.Folder.Name == value)
          return;

        this.Folder.Name = value;
        OnPropertyChanged("Header");
      }
    }

    public bool IsExpanded
    {
      get
      {
        return this.isExpanded;
      }
      set
      {
        if (this.isExpanded != value)
        {
          this.isExpanded = value;
          OnPropertyChanged("IsExpanded");
        }

        // expand all the way up
        if (this.isExpanded && this.Parent != null)
          this.Parent.IsExpanded = true;
      }
    }

    /// <summary>
    /// Gets or sets the whether the folder is selected
    /// </summary>
    public bool IsSelected
    {
      get
      {
        return this.isSelected;
      }
      set
      {
        if (this.isSelected == value)
          return;

        this.isSelected = value;
        OnPropertyChanged("IsSelected");
      }
    }

    public IFolderViewModel Parent
    {
      get;
      private set;
    }

    public ObservableCollection<IFolderViewModel> Children
    {
      get;
      private set;
    }

    #endregion

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    /// <summary>
    /// Raises the PropertyChanged event
    /// </summary>
    protected void OnPropertyChanged(string propertyName)
    {
      PropertyChangedEventHandler handler = PropertyChanged;
      if (handler != null)
        handler(this, new PropertyChangedEventArgs(propertyName));
    }

    #endregion

    public override string ToString()
    {
      return "FolderViewModel: " + this.Folder.Name;
    }
  }
}
